Try to match an off toggle here with the matching on toggle if it
authorMatthias Clasen <mclasen@redhat.com>
Tue, 11 Oct 2005 14:39:17 +0000 (14:39 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Tue, 11 Oct 2005 14:39:17 +0000 (14:39 +0000)
2005-10-11  Matthias Clasen  <mclasen@redhat.com>

* gtk/gtktextbtree.c (_gtk_text_btree_delete): Try to match an off
toggle here with the matching on toggle if it immediately follows.
This is a common case, and handling it here prevents quadratic blowup
in cleanup_line() below.  (#317125)

* gtk/gtktextsegment.h:
* gtk/gtktextsegment.c (_gtk_char_segment_new_from_two_strings): Pass
the character counts into this function instead of computing them
again.

ChangeLog
ChangeLog.pre-2-10
gtk/gtktextbtree.c
gtk/gtktextsegment.c
gtk/gtktextsegment.h

index f3d469d9cebade15350c76125d0b0c3e53cacb81..350c8735dd6ca9c8991c6f837c225487997198f5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2005-10-11  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_delete): Try to match an off 
+       toggle here with the matching on toggle if it immediately follows. 
+       This is a common case, and handling it here prevents quadratic blowup 
+       in cleanup_line() below.  (#317125)
+
+       * gtk/gtktextsegment.h: 
+       * gtk/gtktextsegment.c (_gtk_char_segment_new_from_two_strings): Pass
+       the character counts into this function instead of computing them
+       again.
+
 2005-10-10  Tommi Komulainen  <tommi.komulainen@iki.fi>
 
        * gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error
index f3d469d9cebade15350c76125d0b0c3e53cacb81..350c8735dd6ca9c8991c6f837c225487997198f5 100644 (file)
@@ -1,3 +1,15 @@
+2005-10-11  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtktextbtree.c (_gtk_text_btree_delete): Try to match an off 
+       toggle here with the matching on toggle if it immediately follows. 
+       This is a common case, and handling it here prevents quadratic blowup 
+       in cleanup_line() below.  (#317125)
+
+       * gtk/gtktextsegment.h: 
+       * gtk/gtktextsegment.c (_gtk_char_segment_new_from_two_strings): Pass
+       the character counts into this function instead of computing them
+       again.
+
 2005-10-10  Tommi Komulainen  <tommi.komulainen@iki.fi>
 
        * gtk/gtkfilechooser.h (GtkFileChooserError): Add ALREADY_EXISTS error
index 1e78da9eb561ddfc9dcdeed1e609d1a17ee80be3..98fc15d0366986b0fb94dbe409cea9d475be1ee6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * gtktextbtree.c --
+ * Gtktextbtree.c --
  *
  *      This file contains code that manages the B-tree representation
  *      of text for the text buffer and implements character and
@@ -732,7 +732,7 @@ _gtk_text_btree_delete (GtkTextIter *start,
                                              * of the deletion range. */
   GtkTextLineSegment *last_seg;             /* The segment just after the end
                                              * of the deletion range. */
-  GtkTextLineSegment *seg, *next;
+  GtkTextLineSegment *seg, *next, *next2;
   GtkTextLine *curline;
   GtkTextBTreeNode *curnode, *node;
   GtkTextBTree *tree;
@@ -885,12 +885,29 @@ _gtk_text_btree_delete (GtkTextIter *start,
               seg->next = start_line->segments;
               start_line->segments = seg;
             }
-          else
-            {
+          else if (prev_seg->next &&
+                  seg->type == &gtk_text_toggle_off_type &&
+                  prev_seg->next->type == &gtk_text_toggle_on_type &&
+                  seg->body.toggle.info == prev_seg->next->body.toggle.info)
+           {
+             /* Try to match an off toggle with the matching on toggle
+              * if it immediately follows. This is a common case, and
+              * handling it here prevents quadratic blowup in
+              * cleanup_line() below. See bug 317125.
+              */
+             next2 = prev_seg->next->next;
+             g_free ((char *)prev_seg->next);
+             prev_seg->next = next2;
+             g_free ((char *)seg);
+             seg = NULL;
+           }
+         else
+           {
               seg->next = prev_seg->next;
               prev_seg->next = seg;
             }
-          if (seg->type->leftGravity)
+
+          if (seg && seg->type->leftGravity)
             {
               prev_seg = seg;
             }
@@ -4718,16 +4735,20 @@ cleanup_line (GtkTextLine *line)
   while (changed)
     {
       changed = FALSE;
-      for (prev_p = &line->segments, seg = *prev_p;
-           seg != NULL;
-           prev_p = &(*prev_p)->next, seg = *prev_p)
+      prev_p = &line->segments;
+      for (seg = *prev_p; seg != NULL; seg = *prev_p)
         {
           if (seg->type->cleanupFunc != NULL)
             {
               *prev_p = (*seg->type->cleanupFunc)(seg, line);
               if (seg != *prev_p)
-                changed = TRUE;
+               {
+                 changed = TRUE;
+                 continue;
+               }
             }
+
+         prev_p = &(*prev_p)->next;
         }
     }
 }
index 390e14bcfc08981cc064cba8130ba11afab9bc33..3b961ad66bfdade7d4c04e6b608a67ca87f644c6 100644 (file)
@@ -211,8 +211,12 @@ _gtk_char_segment_new (const gchar *text, guint len)
 }
 
 GtkTextLineSegment*
-_gtk_char_segment_new_from_two_strings (const gchar *text1, guint len1,
-                                        const gchar *text2, guint len2)
+_gtk_char_segment_new_from_two_strings (const gchar *text1, 
+                                       guint        len1, 
+                                       guint        chars1,
+                                        const gchar *text2, 
+                                       guint        len2, 
+                                       guint        chars2)
 {
   GtkTextLineSegment *seg;
 
@@ -227,9 +231,7 @@ _gtk_char_segment_new_from_two_strings (const gchar *text1, guint len1,
   memcpy (seg->body.chars + len1, text2, len2);
   seg->body.chars[len1+len2] = '\0';
 
-  /* In principle this function could probably take chars1 and chars2
-     as args, since it's typically used to merge two char segments */
-  seg->char_count = g_utf8_strlen (seg->body.chars, seg->byte_count);
+  seg->char_count = chars1 + chars2;
 
   if (gtk_debug_flags & GTK_DEBUG_TEXT)
     char_segment_self_check (seg);
@@ -326,8 +328,12 @@ char_segment_cleanup_func (segPtr, line)
     }
 
   newPtr =
-    _gtk_char_segment_new_from_two_strings (segPtr->body.chars, segPtr->byte_count,
-                                            segPtr2->body.chars, segPtr2->byte_count);
+    _gtk_char_segment_new_from_two_strings (segPtr->body.chars, 
+                                           segPtr->byte_count,
+                                           segPtr->char_count,
+                                            segPtr2->body.chars, 
+                                           segPtr2->byte_count,
+                                           segPtr2->char_count);
 
   newPtr->next = segPtr2->next;
 
index def6e258522caac5ab503c0ff79360f183e301ea..691147b08ccd309378d807e0861198433b023e0d 100644 (file)
@@ -158,8 +158,10 @@ GtkTextLineSegment *_gtk_char_segment_new                  (const gchar    *text
                                                             guint           len);
 GtkTextLineSegment *_gtk_char_segment_new_from_two_strings (const gchar    *text1,
                                                             guint           len1,
+                                                           guint           chars1,
                                                             const gchar    *text2,
-                                                            guint           len2);
+                                                            guint           len2,
+                                                           guint           chars2);
 GtkTextLineSegment *_gtk_toggle_segment_new                (GtkTextTagInfo *info,
                                                             gboolean        on);